package sqlstash

import (
	"strings"

	"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
)

type selectQuery struct {
	dialect  migrator.Dialect
	fields   []string // SELECT xyz
	from     string   // FROM object
	limit    int64
	oneExtra bool

	where []string
	args  []any
}

func (q *selectQuery) addWhere(f string, val ...any) {
	q.args = append(q.args, val...)
	// if the field contains a question mark, we assume it's a raw where clause
	if strings.Contains(f, "?") {
		q.where = append(q.where, f)
		// otherwise we assume it's a field name
	} else {
		q.where = append(q.where, q.dialect.Quote(f)+"=?")
	}
}

func (q *selectQuery) addWhereInSubquery(f string, subquery string, subqueryArgs []any) {
	q.args = append(q.args, subqueryArgs...)
	q.where = append(q.where, q.dialect.Quote(f)+" IN ("+subquery+")")
}

func (q *selectQuery) addWhereIn(f string, vals []string) {
	count := len(vals)
	if count > 1 {
		sb := strings.Builder{}
		sb.WriteString(q.dialect.Quote(f))
		sb.WriteString(" IN (")
		for i := 0; i < count; i++ {
			if i > 0 {
				sb.WriteString(",")
			}
			sb.WriteString("?")
			q.args = append(q.args, vals[i])
		}
		sb.WriteString(") ")
		q.where = append(q.where, sb.String())
	} else if count == 1 {
		q.addWhere(f, vals[0])
	}
}

func (q *selectQuery) toQuery() (string, []any) {
	args := q.args
	sb := strings.Builder{}
	sb.WriteString("SELECT ")
	quotedFields := make([]string, len(q.fields))
	for i, f := range q.fields {
		quotedFields[i] = q.dialect.Quote(f)
	}
	sb.WriteString(strings.Join(quotedFields, ","))
	sb.WriteString(" FROM ")
	sb.WriteString(q.from)

	// Templated where string
	where := len(q.where)
	if where > 0 {
		sb.WriteString(" WHERE ")
		for i := 0; i < where; i++ {
			if i > 0 {
				sb.WriteString(" AND ")
			}
			sb.WriteString(q.where[i])
		}
	}

	if q.limit > 0 || q.oneExtra {
		limit := q.limit
		if limit < 1 {
			limit = 20
			q.limit = limit
		}
		if q.oneExtra {
			limit = limit + 1
		}
		sb.WriteString(" LIMIT ?")
		args = append(args, limit)
	}
	return sb.String(), args
}
